<!doctype html>



  


<html class="theme-next pisces use-motion">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />












  
  
  <link href="/vendors/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/vendors/font-awesome/css/font-awesome.min.css?v=4.4.0" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.0.1" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="王雨峰, 博客" />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.0.1" />






<meta name="description" content="老师发来的考点是下面这些（原文）：

类的静态成员和友元
数组作为函数参数，指针作为函数参数，与地址相关的运算『*』和『&amp;amp;』
对象指针与动态内存分配
派生类的构造函数和析构函数，复制构造函数，派生类成员的标识和与访问
虚基类
单目和双目运算符重载
多态程序编写，包括虚函数、纯虚函数以及抽象类

这篇文章中我把这些知识点过一遍，正好我自己也复习一下…如果有错误还请指出，我进行勘误后再发一版。">
<meta property="og:type" content="article">
<meta property="og:title" content="C++考试重点解析 | 七系">
<meta property="og:url" content="http://wangyufeng.org/2015/11/23/cpp-keypoint/index.html">
<meta property="og:site_name" content="王雨峰的博客">
<meta property="og:description" content="老师发来的考点是下面这些（原文）：

类的静态成员和友元
数组作为函数参数，指针作为函数参数，与地址相关的运算『*』和『&amp;amp;』
对象指针与动态内存分配
派生类的构造函数和析构函数，复制构造函数，派生类成员的标识和与访问
虚基类
单目和双目运算符重载
多态程序编写，包括虚函数、纯虚函数以及抽象类

这篇文章中我把这些知识点过一遍，正好我自己也复习一下…如果有错误还请指出，我进行勘误后再发一版。">
<meta property="og:updated_time" content="2015-11-28T08:01:48.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="C++考试重点解析 | 七系">
<meta name="twitter:description" content="老师发来的考点是下面这些（原文）：

类的静态成员和友元
数组作为函数参数，指针作为函数参数，与地址相关的运算『*』和『&amp;amp;』
对象指针与动态内存分配
派生类的构造函数和析构函数，复制构造函数，派生类成员的标识和与访问
虚基类
单目和双目运算符重载
多态程序编写，包括虚函数、纯虚函数以及抽象类

这篇文章中我把这些知识点过一遍，正好我自己也复习一下…如果有错误还请指出，我进行勘误后再发一版。">



<script type="text/javascript" id="hexo.configuration">
  var NexT = window.NexT || {};
  var CONFIG = {
    scheme: 'Pisces',
    sidebar: {"position":"left","display":"post"},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: 0,
      author: '博主'
    }
  };
</script>




  <link rel="canonical" href="http://wangyufeng.org/2015/11/23/cpp-keypoint/"/>

  <title> C++考试重点解析 | 七系 | 王雨峰的博客 </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  










  
  
    
  

  <div class="container one-collumn sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-meta ">
  

  <div class="custom-logo-site-title">
    <a href="/"  class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <span class="site-title">王雨峰的博客</span>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>
  <p class="site-subtitle">随便写点东西，为互联网贡献一些比特~</p>
</div>

<div class="site-nav-toggle">
  <button>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
  </button>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>

 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  
  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                C++考试重点解析 | 七系
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            <span class="post-meta-item-icon">
              <i class="fa fa-calendar-o"></i>
            </span>
            <span class="post-meta-item-text">发表于</span>
            <time itemprop="dateCreated" datetime="2015-11-23T13:06:11+08:00" content="2015-11-23">
              2015-11-23
            </time>
          </span>

          

          
            
          

          

          
          

          
        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>老师发来的考点是下面这些（原文）：</p>
<ol>
<li>类的静态成员和友元</li>
<li>数组作为函数参数，指针作为函数参数，与地址相关的运算『*』和『&amp;』</li>
<li>对象指针与动态内存分配</li>
<li>派生类的构造函数和析构函数，复制构造函数，派生类成员的标识和与访问</li>
<li>虚基类</li>
<li>单目和双目运算符重载</li>
<li>多态程序编写，包括虚函数、纯虚函数以及抽象类</li>
</ol>
<p>这篇文章中我把这些知识点过一遍，正好我自己也复习一下…如果有错误还请指出，我进行勘误后再发一版。这篇文章不是一篇系统的知识点回顾，其中有很多我个人的理解，不甚准确，仅供有限的参考。另外，我的C++学的也比较一般，所以也希望能借此机会和大家多交流。</p>
<p>另外还请注意的是，咱们的课本写的还是挺清楚的，将这些知识点在书上找出来，再看几遍即可。</p>
<p>##1.类的静态成员和友元</p>
<p>###1.1关键字</p>
<ul>
<li>静态成员：static</li>
<li>友元：friend</li>
</ul>
<p>###1.2静态成员<br>定义：如果有一个成员，需要和他所属的<strong>类</strong>直接相关，而不是和由这个类生成的<strong>对象</strong>直接相关，此时需要静态成员。</p>
<p>举例：“北工大学生”作为一个类，可以派生出你，你，你，我，每一个人。而这个类中有一个成员变量“学生总数”，这个成员只和“北工大学生”这个类相关，而不和具体的某个学生对象相关。<br>比如说，“学生总数”这个<strong>成员</strong>，和“王大水”这个<strong>对象</strong>没有关系。</p>
<p>此时，如果修改任意一个对象中的静态成员，所有派生自同一个类的此静态成员都会同时被改变。也就是说，所有的由此类派生出的对象，都共享同一份静态成员，一变都变。</p>
<p>使用方法：在成员的声明前加上<code>static</code>。</p>
<p>比如：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">class</span> BJUT_Student&#123;</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">setTotal</span><span class="params">(<span class="keyword">int</span>)</span></span>;</div><div class="line"><span class="keyword">private</span>:</div><div class="line">    <span class="built_in">string</span> name;</div><div class="line">    <span class="keyword">static</span> <span class="keyword">int</span> total; <span class="comment">//学生总数</span></div><div class="line">&#125;;</div></pre></td></tr></table></figure></p>
<p>此时，total前的<code>static</code>就是将此变量声明为静态成员的意思。</p>
<p>当然，<code>static</code>也可以加在<strong>成员函数</strong>的声明前。有什么用呢？比如说，你想在<strong>类还没实例化之前，就修改static变量的值</strong>，那这个修改用的函数也得是<code>static</code>的。</p>
<p>这块知识基本可以类比Java中学过的<code>Static</code>。</p>
<p>###1.3友元</p>
<p>友元的预备知识：访问的控制与封装，即<code>public</code>，<code>protected</code>，<code>private</code>关键字的功能。</p>
<p>可以这样不严谨但通俗地理解：</p>
<ul>
<li><code>public</code>：谁都能来使用我的东西，来者不拒</li>
<li><code>protected</code>：只有我的孩子孙子（继承自我的类）才能用我的东西</li>
<li><code>private</code>：只有我自己才能用我自己的东西</li>
</ul>
<p>友元的作用，是指定某一个函数(或某一个类的成员函数)“为自己的好朋友”，即可以使用自己的private内容。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">class</span> BJUT_Student&#123;</div><div class="line"><span class="function"><span class="keyword">friend</span> <span class="keyword">void</span> <span class="title">print</span> <span class="params">(<span class="keyword">const</span> BJUT_Student &amp; pb)</span></span>;    <span class="comment">//const引用</span></div><div class="line"><span class="keyword">public</span>:</div><div class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">setTotal</span><span class="params">(<span class="keyword">int</span>)</span></span>;</div><div class="line"><span class="keyword">private</span>:</div><div class="line">    <span class="built_in">string</span> name;</div><div class="line">    <span class="keyword">static</span> <span class="keyword">int</span> total; <span class="comment">//学生总数</span></div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">print</span><span class="params">(<span class="keyword">const</span> BJUT_Student &amp; pb)</span></span></div><div class="line">&#123;</div><div class="line">    <span class="comment">//输出信息用的代码</span></div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</div><div class="line">    BJUT_Student stu1;</div><div class="line">    print (stu1);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>如果print是一个用来输出学生对象中信息的函数，那这种方法(加friend)就相当于给了<code>print</code>函数一个特殊的权限。</p>
<p><code>friend</code>作用在<strong>类的成员函数</strong>时，用法也是一样的。</p>
<p>友元声明不写在<code>public</code>或<code>private</code>区域中。</p>
<p>总之，两个类之间需要共享数据的时候，可以使用友元。但请注意，友元实质上破坏了类的封装性。Java中就没有友元函数这一设定。</p>
<p>##2.数组作为函数参数，指针作为函数参数，与地址相关的运算『*』和『&amp;』</p>
<p>###2.1.数组作为函数参数</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">sum</span><span class="params">(<span class="keyword">int</span> * a)</span></span>;  <span class="comment">//声明方法1</span></div><div class="line"><span class="comment">//void sum(int [] a);   //声明方法2，这样也行</span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</div><div class="line">    <span class="keyword">int</span> a[<span class="number">20</span>];  <span class="comment">//声明数组</span></div><div class="line">    sum (a);    <span class="comment">//传递这个数组为函数参数</span></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>C语言里学过。形式大概就是上面这样。</p>
<p>###2.2指针作为函数参数，与地址相关的运算 <code>*</code> 和 <code>&amp;</code></p>
<p>C和C++语言中，同一个符号在不同的场合会有不同的意思。在和地址相关时：</p>
<ul>
<li><code>&amp;</code> ： 取址符</li>
<li><code>*</code> ： 取值符</li>
</ul>
<p>他们俩互为逆运算。<code>&amp;</code>就是取一个变量的地址（通常情况下，也就是指针的意思，但请不要认为地址==指针）。</p>
<p><code>*</code>的话就是“取一个地址内的值”，和上面的<code>&amp;</code>的操作正好相反。</p>
<p>就好比说，宿舍号“424”是一个地址，你取424的值，即<code>*424</code>，取出来的就是“王大水”这个值。如果你对“王大水”进行取址，即<code>&amp;王大水</code>，结果就是424.</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span> * p)</span></span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</div><div class="line">    <span class="keyword">int</span> a = <span class="number">233</span>;</div><div class="line">    <span class="keyword">int</span> * pointer1 = &amp;a;    <span class="comment">//将a的地址赋给指针pointer1</span></div><div class="line">    func(pointer1); <span class="comment">//指针作为函数参数</span></div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span> <span class="params">(<span class="keyword">int</span> * p)</span></span>&#123;</div><div class="line">    <span class="built_in">cout</span> &lt;&lt; p;      <span class="comment">//输出的是a的地址，即主函数中的&amp;a</span></div><div class="line">    <span class="built_in">cout</span> &lt;&lt; *p;     <span class="comment">//输出的是a的值，即233</span></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>##3.对象指针与动态内存分配</p>
<p>###3.1.对象指针</p>
<p>如果有一个指针<strong>指向了一个对象</strong>，那这个指针就是<strong>对象指针</strong>了。比如：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</div><div class="line">    BJUT_Student * pb = student1;   <span class="comment">//pb指向了对象student1，pb的类型是"BJUT_Student"</span></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>###3.2.动态内存分配</p>
<p>咱们在C语言里学过<code>malloc</code>，写法比较繁琐，一般是</p>
<figure class="highlight plain"><figcaption><span>* BJUT_Student = (BJUT_Student*)malloc(sizeof(BJUT_Student));```</span></figcaption><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">在C++里大幅简化了这个功能（申请内存），约等于</div><div class="line"></div><div class="line">```BJUT_Student * student1 = new BJUT_Student();</div></pre></td></tr></table></figure>
<p>方便多了吧。</p>
<p>在C++里，尽量使用<code>new</code>，尽量不使用属于C语言的函数(例如<code>malloc</code>)。</p>
<p>##4.派生类的构造函数和析构函数，复制构造函数，派生类成员的标识和与访问</p>
<p>###4.1.派生类的构造函数和析构函数</p>
<ul>
<li>构造函数：用来在新生成一个对象时初始化一些内容</li>
<li>析构函数：用来执行在销毁一个对象时要做的一些事情</li>
</ul>
<p>一般情况下，手写构造函数比较频繁，手写析构函数的机会不多。C++ Runtime 会自动为我们做一些事。</p>
<p>ps：构造函数在定义的时候，需要和<strong>类名相同</strong>。</p>
<p>派生类：即从已有的类继承而来的类。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">class</span> A     <span class="comment">//基类A</span></div><div class="line">&#123;</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    A(<span class="keyword">int</span> x)&#123;</div><div class="line">        a = x;</div><div class="line">    &#125;</div><div class="line"><span class="keyword">private</span>:</div><div class="line">    <span class="keyword">int</span> a;</div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="keyword">class</span> B : <span class="keyword">public</span> A</div><div class="line">&#123;</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    B(<span class="keyword">int</span> x, <span class="keyword">int</span> y) : A(x)  <span class="comment">//派生类的构造函数，冒号后的是“初始化列表”</span></div><div class="line">    &#123;</div><div class="line">        b = y;</div><div class="line">    &#125;</div><div class="line"><span class="keyword">private</span>:</div><div class="line">    <span class="keyword">int</span> b;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></div><div class="line">&#123;</div><div class="line">    <span class="function">B <span class="title">b1</span><span class="params">(<span class="number">1</span>,<span class="number">2</span>)</span></span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>就是这个意思，B继承自A。派生类的构造函数执行的时候，先执行父类的构造函数，也就是说<strong>初始化列表</strong>中的<code>: A(x)</code>.</p>
<p>析构函数也和类同名，但前面加了一个<code>~</code>，例如<code>~B(){//xxxxx}</code>。上述代码中没写析构函数。</p>
<p>派生类中的析构函数，执行的时候和构造函数的顺序相反，即先析构自己，再析构父类。<strong>除非</strong>父类的析构函数是虚函数(virtual)。</p>
<p>我还从来没实际用过析构函数，所以对这块不了解。一般情况下，对象销毁的时候，系统都自动为我们执行很多相当于析构函数的工作了。</p>
<p>关于“初始化列表”，可以简单的说：能用初始化列表的场合，都尽量使用初始化列表。尤其是，当某些const类型和引用类型的成员变量需要被初始化时，必须使用初始化列表，因为const或引用变量无法被复制（除初始化时）。</p>
<p>##4.2.复制构造函数</p>
<p>就我所知，一般在</p>
<ul>
<li>将对象作为参数传递，且为<strong>值传递</strong>的时候需要用到复制构造函数。</li>
<li>return一个对象。</li>
<li>纯粹复制一个对象。</li>
<li>构造一个对象时需要复制另外一个对象。</li>
</ul>
<p>说白了就是用来复制一个对象用的函数。关于值传递和地址传递的区别，可以参考我之前写过的文章。</p>
<p>复制构造函数的写法：一个<strong>参数为类的引用</strong>的构造函数，参数最好是const。例如：</p>
<p>复制构造函数在本质上还是构造函数，区别在于参数不同，用途不同。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">B(<span class="keyword">const</span> B&amp;);    <span class="comment">//复制构造函数的声明</span></div><div class="line"></div><div class="line">B:B(<span class="keyword">const</span> B&amp; p)&#123; <span class="comment">//复制构造函数的定义</span></div><div class="line">    b = p.b;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>我的理解是：复制构造函数，就是一个明确指定“如何复制一个对象”的函数。</p>
<p>#4.3.派生类成员的标识与访问</p>
<p>不明白这是在说啥…</p>
<p>#5.虚基类</p>
<p>即在继承一个类的时候，在被继承的类名前面加个virtual。这在多继承时才会被用到。是为了消除二义性。</p>
<p>比如有基类A，B继承自A，C继承自A，又有D多继承自B和C。此时D中继承自A的成员，到底是哪一个A呢？（因为B和C分别复制了一份A的成员）这就产生了冲突。</p>
<p>如果在B和C继承A的时候，将A声明为<strong>虚基类</strong>即可解决这个问题，虚基类会确保A中的成员有且只有一份，D调用的时候就不会产生冲突。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></div><div class="line"></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="keyword">class</span> A&#123;</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    <span class="keyword">int</span> i;</div><div class="line">    <span class="function"><span class="keyword">void</span> <span class="title">print</span><span class="params">()</span></span>&#123;<span class="built_in">cout</span> &lt;&lt; i &lt;&lt; <span class="built_in">endl</span>;&#125;</div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="keyword">class</span> B : <span class="keyword">virtual</span> <span class="keyword">public</span> A&#123;     <span class="comment">//虚继承</span></div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="keyword">class</span> C : <span class="keyword">virtual</span> <span class="keyword">public</span> A&#123;     <span class="comment">//虚继承</span></div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="keyword">class</span> D : <span class="keyword">public</span> B, <span class="keyword">public</span> C&#123;</div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</div><div class="line">    A a;</div><div class="line">    B b;</div><div class="line">    C c;</div><div class="line"></div><div class="line">    a.i = <span class="number">1</span>;</div><div class="line">    a.print();</div><div class="line"></div><div class="line">    b.i = <span class="number">2</span>;</div><div class="line">    b.print();</div><div class="line"></div><div class="line">    c.i = <span class="number">3</span>;</div><div class="line">    c.print();</div><div class="line"></div><div class="line">    D d;</div><div class="line">    d.i = <span class="number">4</span>;    <span class="comment">//消除了二义性，如果不用虚继承，此处编译出错</span></div><div class="line">    d.print();</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>虚基类这事儿不常用。可以参考Java语言：根本就没有多继承，所以也不用操心这些事儿。</p>
<p>注：在Java中，和「多继承」类似的功能一般靠接口(interface)实现。</p>
<p>##6.单目和双目运算符重载</p>
<p>运算符重载是C++的一个特点，另一门面相对象语言即Java中，就没有运算符重载。因为他们的设计哲学有区别吧。</p>
<p>之前咱们学过函数的重载，即，当函数名相同，但函数参数列表不同时，程序会根据咱们实际所给的参数列表，动态地选择应调用的函数。</p>
<p>运算符重载也差不多，经过重载，同样地运算符在参与不同的数据类型（比如：int，double 就是两种不同的数据类型），会有不同的表现。</p>
<p>这是双目运算符的重载：(课本P310)</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">Complex <span class="keyword">operator</span>+ (<span class="keyword">const</span> Complex &amp;c2) <span class="keyword">const</span>;</div><div class="line"></div><div class="line">Complex::<span class="keyword">operator</span>+ (<span class="keyword">const</span> Complex &amp;c2) <span class="keyword">const</span> &#123;</div><div class="line">    <span class="keyword">return</span> Complex(<span class="keyword">this</span>.real + c2.real, <span class="keyword">this</span>.imag + c2.imag);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>在双目运算符的重载中，运算符左边的操作数就是this。this一般可以省略。右操作数作为参数传递进来，也就是说这里的c2.</p>
<p>为什么需要重载这个加号呢？因为<code>Complex</code>类型是用户自定义的类型，C++编译器不知道该如何将两个这样的对象“加”在一起，需要用户手动描述。</p>
<p>单目运算符的重载也是一个意思。比较常用的单目运算符重载是<code>++</code>,<code>--</code>，值得注意的是，单目运算符重载一般没有参数（被运算的数作为this指针隐式传递）。</p>
<p>还有一种情况，即用友元函数进行运算符重载，这样的话，双目运算符重载就有两个参数，单目运算符重载就有一个参数。因为友元函数运算符重载没有this指针。</p>
<p>关于自增运算符前置、后置的重载，可以参考课本P312，非常清楚。</p>
<p>##7.多态程序编写，包括虚函数、纯虚函数以及抽象类</p>
<p>###7.1.多态，虚函数</p>
<p>什么是多态呢…</p>
<p>书上的定义不太好理解，一般都是类似于“对同一个消息作用在不同的对象上，会产生不同的效果”。你可能会问，这不是废话吗？比如有个父类Animal，子类Dog，我让Animal“吃”，和让Dog“吃”，效果肯定不一样啊，这还用系统给我判断？</p>
<p>你说的没什么错。按照我的理解，什么时候需要多态性呢？</p>
<p>比如有个<code>Animal</code>类型的指针<code>a</code>，这个指针<code>a</code>指向<code>Animal</code>的时候，你调用<code>a.eat()</code>。指针再指向<code>Dog</code>的时候，你又调用<code>a.eat()</code>。此时如果能分别正确调用<code>Animal</code>和<code>Dog</code>的<code>eat()</code>方法，那这就是多态。</p>
<p>如果你分别用指向<code>Animal</code>和指向<code>Dog</code>的指针，分别调用<code>eat()</code>，这就不叫多态。</p>
<p>多态这件事和<strong>继承</strong>是<strong>紧密相连</strong>的。</p>
<p>咱们应该是都学过Java了，为啥Java中没怎么提到过多态呢？确实如此，因为Java中的类的继承，在默认的情况下就已经实现了多态了。</p>
<p>但C++就没这么自动化，如果想让一个父类的某个成员函数能实现多态性，就必须规定这个函数为<code>虚函数</code>。</p>
<p>用刚才那个例子来说，也就是说得让Animal类中的eat()方法前加上一个virtual。类似：</p>
<figure class="highlight plain"><figcaption><span>void eat()&#123;//xxx&#125;;```</span></figcaption><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">###7.2.纯虚函数</div><div class="line"></div><div class="line">纯虚函数是一种特殊的虚函数。即只声明，不实现定义。由继承下去的子类去具体实现。</div><div class="line"></div><div class="line">写法是这样：</div><div class="line"></div><div class="line">```virtual &lt;类型&gt;&lt;函数名&gt;(&lt;参数表&gt;)=0;</div></pre></td></tr></table></figure>
<p>加了一个<code>=0</code>。注意,<code>virtual</code>也不能少。</p>
<p>我个人理解：纯虚函数对应Java中的抽象(Abstract)函数。</p>
<p>###7.3.抽象类</p>
<p>只要是包含了纯虚函数的类就自动被归为抽象类。和Java中的抽象类类似，不能被实例化为对象，只能被继承。</p>
<p>抽象类中至少存在一个纯虚函数；存在纯虚函数的类一定是抽象类。存在纯虚函数是成为抽象类的充要条件。</p>
<h2 id="完毕。"><a href="#完毕。" class="headerlink" title="完毕。"></a>完毕。</h2><p>C++的确很有用，非常强大，效率很高。坦诚地讲，也很有学习的必要。但从我个人的角度，以及我目前对C++及其浅薄的认识，我不是很喜欢C++这门语言给我的感觉。强类型的面向对象语言中，我更喜欢Java。目前我正在(以极其缓慢、肉眼几乎难以辨别的速度)学习Python，如果有同感兴趣的朋友请一起来交流。</p>
<p>当然了，我想强调的是，我承认C++作为<strong>基石</strong>的作用。我也同意，作为计算机专业的学生，有必要对C++进行相对深度的学习。</p>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>

    <footer class="post-footer">
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2015/10/27/DC-regulated-power/" rel="next" title="直流稳压电源(电路实验1)笔记">
                <i class="fa fa-chevron-left"></i> 直流稳压电源(电路实验1)笔记
              </a>
            
          </div>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2015/12/01/shu-zi-luo-ji-shi-yan-tips-1/" rel="prev" title="数字逻辑实验，如何使用键盘">
                数字逻辑实验，如何使用键盘 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel ">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/images/avatar.gif"
               alt="Alan" />
          <p class="site-author-name" itemprop="name">Alan</p>
          <p class="site-description motion-element" itemprop="description">Alan Wang's personal blog.</p>
        </div>
        <nav class="site-state motion-element">
          <div class="site-state-item site-state-posts">
            <a href="/archives">
              <span class="site-state-item-count">57</span>
              <span class="site-state-item-name">日志</span>
            </a>
          </div>

          
            <div class="site-state-item site-state-categories">
              
                <span class="site-state-item-count">9</span>
                <span class="site-state-item-name">分类</span>
              
            </div>
          

          
            <div class="site-state-item site-state-tags">
              
                <span class="site-state-item-count">4</span>
                <span class="site-state-item-name">标签</span>
              
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
        </div>

        
        

        
        

      </section>

      
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">
            
              
            
            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#完毕。"><span class="nav-number">1.</span> <span class="nav-text">完毕。</span></a></li></ol></div>
            
          </div>
        </section>
      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy; 
  <span itemprop="copyrightYear">2016</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Alan</span>
</div>

<div class="powered-by">
  Powered by <a class="theme-link" href="https://hexo.io">Hexo</a> 
</div>

<div class="theme-info">
  主题 -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Pisces
  </a>
</div>

        

        
      </div>
    </footer>

    <div class="back-to-top">
      <i class="fa fa-arrow-up"></i>
    </div>
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  



  
  <script type="text/javascript" src="/vendors/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/vendors/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/vendors/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/vendors/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/vendors/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/vendors/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.0.1"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.0.1"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.0.1"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.0.1"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.0.1"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.0.1"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.0.1"></script>



  



  




  
  

  

  

  

</body>
</html>
